/* eslint-disable array-callback-return */
/* eslint-disable no-lonely-if */
/* eslint-disable no-plusplus */
/* eslint-disable @typescript-eslint/explicit-function-return-type */
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
import { ref, provide, inject, computed, watch } from 'vue';
import { PivotData } from '@/pivottable/helper';
import { numberFormat } from '@/pivottable/helper/utilities';

const PIVOT_DATA_KEY = Symbol('pivotData');

export function providePivotData(props) {
  const error = ref(null);

  const groupData = ref({});

  const pivotData = computed(() => {
    try {
      return new PivotData(props);
    } catch (err) {
      console.error(err.stack);
      error.value = 'An error occurred computing the PivotTable results.';
      return null;
    }
  });

  const vals = computed(() => {
    const values = pivotData.value?.props.vals || [];
    if (values.length > 0) {
      return values[0].split(',');
    }
    return [];
  });
  const rowKeys = computed(() => pivotData.value?.getRowKeys() || []);
  const colKeys = computed(() => {
    return pivotData.value?.getColKeys() || [];
  });
  const colAttrs = computed(() => {
    return pivotData.value?.props.cols || [];
  });
  const rowAttrs = computed(() => pivotData.value?.props.rows || []);
  const colorScaleGenerator = props.tableColorScaleGenerator;

  const getAggregator = (rowKey, colKey) =>
    pivotData.value?.getAggregator(rowKey, colKey) || {
      value: () => null,
      format: () => '',
    };

  const grandTotalAggregator = computed(() => {
    return pivotData.value
      ? getAggregator([], [])
      : {
          value: () => null,
          format: () => '',
        };
  });

  const allColorScales = computed(() => {
    const values = rowKeys.value.reduce((acc, r) => {
      return acc.concat(colKeys.value.map(c => getAggregator(r, c).value()));
    }, []);
    return colorScaleGenerator(values);
  });
  const rowColorScales = computed(() =>
    rowKeys.value.reduce((scales, r) => {
      scales[r] = colorScaleGenerator(
        colKeys.value.map(x => getAggregator(r, x).value()),
      );
      return scales;
    }, {}),
  );
  const colColorScales = computed(() =>
    colKeys.value.reduce((scales, c) => {
      scales[c] = colorScaleGenerator(
        rowKeys.value.map(x => getAggregator(x, c).value()),
      );
      return scales;
    }, {}),
  );

  const valueCellColors = (rowKey, colKey, value) => {
    if (props.heatmapMode === 'full') {
      return allColorScales.value(value);
    }
    if (props.heatmapMode === 'row') {
      return rowColorScales.value[rowKey](value);
    }
    if (props.heatmapMode === 'col') {
      return colColorScales.value[colKey](value);
    }
    return {};
  };
  const rowTotalValues = colKeys.value.map(x => getAggregator([], x).value());
  const rowTotalColors = value => {
    if (!props.heatmapMode) return {};

    return colorScaleGenerator(rowTotalValues)(value);
  };
  const colTotalValues = rowKeys.value.map(x => getAggregator(x, []).value());
  const colTotalColors = value => {
    if (!props.heatmapMode) return {};

    return colorScaleGenerator(colTotalValues)(value);
  };

  const spanSize = (arr, i, j) => {
    let x;
    if (i !== 0) {
      let noDraw = true;
      for (x = 0; x <= j; x++) {
        if (arr[i - 1][x] !== arr[i][x]) {
          noDraw = false;
        }
      }
      if (noDraw) {
        return -1;
      }
    }

    let len = 0;
    while (i + len < arr.length) {
      let stop = false;
      for (x = 0; x <= j; x++) {
        if (arr[i][x] !== arr[i + len][x]) {
          stop = true;
        }
      }
      if (stop) {
        break;
      }
      len++;
    }
    return len;
  };

  const multiDimArrayToTree = (
    arr,
    keys = ['level1', 'level2', 'level3'],
    depth = 0,
    parentKey = [],
  ) => {
    // 如果keys不够用，自动补充层级名
    if (depth >= keys.length) {
      keys.push(`level${keys.length + 1}`);
    }

    const currentKey = keys[depth];
    const result = [];
    const map = new Map(); // 使用Map来分组

    // 遍历数组元素
    arr.forEach(item => {
      // 跳过空元素或无效元素
      if (
        item === undefined ||
        item === null ||
        (Array.isArray(item) && item.length === 0)
      ) {
        return;
      }

      // 判断当前元素是数组还是值
      if (Array.isArray(item)) {
        // 处理多维数组情况
        const firstItem = item[0].toString();
        parentKey.push(firstItem);
        // 如果还没有这个key的分组，创建一个
        if (!map.has(firstItem)) {
          const valueKey = parentKey.join(String.fromCharCode(0));
          const aggregator = getAggregator(parentKey, []);
          const node = {
            [currentKey]: firstItem,
            codeName: currentKey,
            label: firstItem,
            srfkey: valueKey,
            value: aggregator.value(),
            format: aggregator.format(aggregator.value()),
            children: [],
          };
          if (depth === keys.length - 1) {
            const treeItem = pivotData.value.tree[valueKey];
            node.items = Object.keys(treeItem).map(key => {
              const value = treeItem[key].value();
              return {
                codeName: key,
                value,
                format: treeItem[key].format(value),
              };
            });
          }
          map.set(firstItem, node);
          result.push(node);
        }

        // 递归处理剩余元素
        const remainingItems = item.slice(1);
        if (remainingItems.length > 0) {
          map
            .get(firstItem)
            .children.push(
              ...multiDimArrayToTree(
                [remainingItems],
                keys,
                depth + 1,
                parentKey,
              ),
            );
        }
      } else {
        // 处理叶子节点（最后一层）
        result.push({
          [currentKey]: item,
        });
      }
      parentKey = [];
    });

    return result;
  };

  const reduceItems = items => {
    return items.reduce((acc, item) => {
      const index = acc.findIndex(x => x.codeName === item.codeName);
      if (index !== -1) {
        acc[index].value += item.value;
      } else {
        acc.push(item);
      }
      return acc;
    }, []);
  };

  const fillGroupData = items => {
    let resValue = 0;
    const resItems = [];
    items.forEach(item => {
      if (item.children && item.children.length > 0) {
        const { value, tempItems } = fillGroupData(item.children);
        item.value = value;
        item.items = tempItems;
        if (!item.format) {
          const fn = numberFormat();
          item.format = fn(item.value);
        }
      }
      if (item.items) {
        resItems.push(...item.items);
      }
      resValue += item.value;
    });
    return { value: resValue, tempItems: reduceItems(resItems) };
  };

  const calcGroupData = () => {
    const treeData = pivotData.value.tree;
    const keys = Object.keys(treeData).map(key =>
      key.split(String.fromCharCode(0)),
    );
    let hasEmpty = false;
    const index = keys.findIndex(key => key.indexOf('') === 0);
    if (index !== -1) {
      keys.splice(index, 1);
      hasEmpty = true;
    }
    const result = multiDimArrayToTree(keys, rowAttrs.value);
    fillGroupData(result);
    if (hasEmpty) {
      const key = ' '.repeat(rowAttrs.value.length - 1).split(' ');
      const Aggregator = getAggregator(key, []);
      result.push({
        codeName: 'empty',
        label: '无',
        srfkey: 'empty',
        value: Aggregator.value(),
        format: Aggregator.format(Aggregator.value()),
      });
    }
    groupData.value = result;
  };

  watch(
    () => [pivotData.value.tree],
    () => {
      calcGroupData();
    },
    { immediate: true, deep: true },
  );

  const pivotDataContext = {
    pivotData,
    rowKeys,
    colKeys,
    colAttrs,
    rowAttrs,
    vals,
    getAggregator,
    grandTotalAggregator,
    spanSize,
    valueCellColors,
    rowTotalColors,
    colTotalColors,
    error,
    groupData,
  };

  provide(PIVOT_DATA_KEY, pivotDataContext);
  return pivotDataContext;
}

export function useProvidePivotData() {
  return inject(PIVOT_DATA_KEY);
}
